extends Spatial
const Npc_definition = preload("res://src/npc_definition.gd")
const haggle_curve = preload("res://haggle_curve.tres")

var first_name = ""
var last_name = ""
var definition : Npc_definition
var reason # for shopping
var memory # TODO store transactions and name as resource
var astar : AStar = null
var path = null
var speed = 0.1
var haggle_count = 0

enum Npc_state {
	UNKNOWN=0
	BROWSING=1,
	AT_COUNTER=2,
	LEAVING=3,
}
var state = Npc_state.UNKNOWN

class Line:
	var speakers = []
	var text = ""
	var emote = ""
	var animation = null
	func _init(s, t, e=""):
		speakers = [s]
		text = t
		emote = e


func _ready():
	speed = rand_range(0.02, 0.1)

func spawn_shopper(definition_arg, reason_arg, memory=null):
	# TODO localize
	self.definition = definition_arg
	definition.name_pool["en"]["first"].shuffle()
	definition.name_pool["en"]["last"].shuffle()
	first_name = definition.name_pool["en"]["first"][0]
	last_name = definition.name_pool["en"]["last"][0]
	self.reason = reason_arg
	$Sprite3D.texture = load(definition.prefix + ".png")
	$Sprite3D.scale = Vector3(0.1,0.1,0.1)
	state = Npc_state.BROWSING
	
func full_name():
	# TODO localize
	return first_name + " " + last_name
	
func _physics_process(delta):
	if not path and astar:
		if state == Npc_state.BROWSING:
			find_path()
		elif state == Npc_state.LEAVING:
			queue_free()
	if path and path.size() > 0:
		var next = path[0]
		self.global_transform.origin = self.global_transform.origin.linear_interpolate(next, speed)
		if self.global_transform.origin.distance_squared_to(next) < 0.1:
			path.remove(0)
		#self.transform.origin += Vector3(rand_range(-0.15, 0.15), 0, rand_range(-0.15, 0.15))

func find_path():
	var points = astar.get_points()
	var index = randi() % points.size()
	var last_point = astar.get_closest_point(self.global_transform.origin)
	path = astar.get_point_path(last_point, points[index])
	
func move_to_counter(target:Vector3):
	state = Npc_state.AT_COUNTER
	find_path_to(target)
	
func leave_through_door(target:Vector3):
	state = Npc_state.LEAVING
	find_path_to(target)

func find_path_to(target:Vector3):
	var last_point = astar.get_closest_point(self.global_transform.origin)
	var target_id = astar.get_closest_point(target)
	path = astar.get_point_path(last_point, target_id)


func lines(id, vars={}):
	var result = []
	# TODO localize
	var text :String = self.definition.lines["en"][id]
	for k in vars.keys():
		text = text.replace("%" + k, vars[k])
	var emote = ""
	if ("_outrage" in id) or ("_bad" in id):
		emote = "_angry"
	if ("_good" in id) or ("_okay" in id) or ("_perfect" in id):
		emote = "_happy"
	var line = Line.new(self, text, emote)
	result.append(line)
	# TODO .1 .2 variations
	return result
	
func request_match_line(item, request):
	var prefix = "request_matched"
	if not item:
		return prefix + "_nothing"
	#return prefix + "_okay"
	if request["category"] and item.definition.category == request["category"]:
		return prefix + "_good"
	var matches_all_tags = true
	for a in request["adjectives"]:
		if not (a in item.definition.tags):
			matches_all_tags = false
			break
	if matches_all_tags:
		return prefix + "_good"
#	return prefix + "_perfect"
	return prefix + "_bad"

# lower rehaggle_chance on consecutive haggles so prices in the accepted area get accepted
func haggle_rating(value, base, prefix = "buy_price", rehaggle_chance:float=1.0):
	# TODO include memory
	var percent = float(value) / max(float(base), 1.0)
	if value > definition.money_max:
		return "out_of_money"
	var outrage_rating = definition.accepts_markup_buy + ((definition.accepts_markup_buy - 1.0)*2.0)
	var much_rating = definition.accepts_markup_buy + ((definition.accepts_markup_buy - 1.0)*1.5)
	var normal_rating = definition.accepts_markup_buy + ((definition.accepts_markup_buy - 1.0)*1.2)
	if percent >= outrage_rating:
		return prefix + "_outrage"
	if percent >= much_rating:
		return prefix + "_much"
	if percent >= normal_rating:
		return prefix
	if percent >= definition.accepts_markup_buy:
		return prefix + "_little"
	
	#TODO test this
	var chance_uncurved = ((percent-1.0) / max(definition.accepts_markup_buy-1.0, 0.01))
	var chance = (haggle_curve.interpolate(chance_uncurved) + definition.haggle_chance_min) * definition.haggle_chance_max * rehaggle_chance
	if randf() < chance:
		return prefix + "_little"
	# TODO good_much
	return prefix + "_good"

func attempt_rehaggle():
	haggle_count += 1
	if haggle_count > 2:
		return false
	if haggle_count == 2:
		return (randf() > 0.5)
	return true

func portrait(emote=""):
	var path = definition.prefix + emote + ".png"
	if OS.has_feature("standalone"):
		var resource = load(path)
		return resource
	else:
		var f = File.new()
		if f.file_exists(path):
			return load(path)
	return preload("res://2d/unknown_icon.png")
